#include "BlurEffect.h"
#include "Game.h"
#include <assert.h>

void BlurEffect::Initialize(BlurOrientation pOrientation)
{
	HRESULT result;
	ID3D10Blob* errorMessage;
	
	unsigned int numElements;
	D3D10_PASS_DESC passDesc;

	mDevice = CDirect3D::Instance()->GetDevice();
	mDeviceContext = CDirect3D::Instance()->GetDeviceContext();

	DWORD shaderFlags = D3D11_CREATE_DEVICE_DEBUG ;
	// Initialize the error message.
	errorMessage = 0;

	ID3D10Blob* compileShader;
	result = D3DX11CompileFromFile(L"Contents\\Shaders\\BlurEffect.fx", 0, 0, 0, "fx_5_0", shaderFlags, 0, 0, &compileShader, &errorMessage, 0);

	//	char* compileErrors = (char*)(errorMessage->GetBufferPointer());
	//assert(!FAILED(result));
	D3DX11CreateEffectFromMemory(compileShader->GetBufferPointer(), compileShader->GetBufferSize(), 0, mDevice, &mEffect);

		// Get a pointer to the technique inside the shader.
	if(pOrientation == HorizontalBlur)
	{
		mTechnique = mEffect->GetTechniqueByName("HorizontalBlurTechnique");
	}
	else
	{
		mTechnique = mEffect->GetTechniqueByName("VerticalBlurTechnique");
	}
	

	D3D11_INPUT_ELEMENT_DESC polygonLayout[2];
	polygonLayout[0].SemanticName = "POSITION";
	polygonLayout[0].SemanticIndex = 0;
	polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
	polygonLayout[0].InputSlot = 0;
	polygonLayout[0].AlignedByteOffset = 0;
	polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
	polygonLayout[0].InstanceDataStepRate = 0;

	polygonLayout[1].SemanticName = "TEXCOORD";
	polygonLayout[1].SemanticIndex = 0;
	polygonLayout[1].Format = DXGI_FORMAT_R32G32_FLOAT;
	polygonLayout[1].InputSlot = 0;
	polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
	polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
	polygonLayout[1].InstanceDataStepRate = 0;

	// Get a count of the elements in the layout.
	numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]);

	// Create the input layout.
	D3DX11_PASS_SHADER_DESC effectVsDesc;
	mTechnique->GetPassByIndex(0)->GetVertexShaderDesc(&effectVsDesc);
	D3DX11_EFFECT_SHADER_DESC  effectVsDesc2;
	effectVsDesc.pShaderVariable->GetShaderDesc(effectVsDesc.ShaderIndex, &effectVsDesc2);
	const void *vsCodePtr = effectVsDesc2.pBytecode;
	unsigned vsCodeLen = effectVsDesc2.BytecodeLength;

	result = mDevice->CreateInputLayout(polygonLayout, numElements, vsCodePtr, vsCodeLen, &mInputLayout);

	// Get pointers to the three matrices inside the shader so we can update them from this class.
	mFxMatrixWorld = mEffect->GetVariableByName("worldMatrix")->AsMatrix();
	mFxMatrixView = mEffect->GetVariableByName("viewMatrix")->AsMatrix();
	mFxMatrixProjection = mEffect->GetVariableByName("projectionMatrix")->AsMatrix();

	// Get pointer to the texture resource inside the shader.
	mFxTexture = mEffect->GetVariableByName("shaderTexture")->AsShaderResource();

	// Get a pointer to the screen width inside the shader.
	mFxViewWidth = mEffect->GetVariableByName("screenWidth")->AsScalar();
}

void BlurEffect::Uninit()
{

}

void BlurEffect::SetTransformsMatrices(const XMFLOAT4X4 &pWorldMatrix, const XMFLOAT4X4 &pViewMatrix, const XMFLOAT4X4 &pProjectionMatrix)
{
	mFxMatrixWorld->SetMatrix(reinterpret_cast<const float*>(&pWorldMatrix));
	mFxMatrixView->SetMatrix(reinterpret_cast<const float*>(&pViewMatrix));
	mFxMatrixProjection->SetMatrix(reinterpret_cast<const float*>(&pProjectionMatrix));
}

void BlurEffect::SetTextureToBlur(ID3D11ShaderResourceView *pTexture)
{
	mFxTexture->SetResource(pTexture);
}

void BlurEffect::SetViewWidth(float pWidth)
{
	mFxViewWidth->SetFloat(pWidth);
}

void BlurEffect::Render(int pIndexCount)
{
	mDeviceContext->IASetInputLayout(mInputLayout);	
	mTechnique->GetPassByIndex(0)->Apply(0, mDeviceContext);
	mDeviceContext->Draw(pIndexCount, 0);
}
